package com.gdones.gpt.bus.webAccount.service.impl;

import cn.hutool.core.util.IdUtil;
import cn.hutool.json.ObjectMapper;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.PageDTO;
import com.gdones.common.core.dto.MyPageBand;
import com.gdones.common.core.dto.MyPager;
import com.gdones.common.core.dto.MyResult;
import com.gdones.gpt.bus.webAccount.dto.GptWebaccount;
import com.gdones.gpt.bus.webAccount.dto.GptWebaccountInfo;
import com.gdones.gpt.bus.webAccount.mapper.GptWebaccountInfoMapper;
import com.gdones.gpt.bus.webAccount.mapper.GptWebaccountMapper;
import com.gdones.gpt.bus.webAccount.service.IGptWebaccountService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;

import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.io.IOException;
import java.math.BigDecimal;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author GaoJingBo
 * @since 2023-05-20
 */
@Service
@RefreshScope
public class GptWebaccountServiceImpl extends ServiceImpl<GptWebaccountMapper, GptWebaccount> implements IGptWebaccountService {

    @Autowired
    private GptWebaccountInfoMapper infoMapper;

    @Value("${mygpt.gptpath}")
    private String gptpath;

    private final OkHttpClient client;

    public GptWebaccountServiceImpl() {

        TrustManager[] trustManagers = new TrustManager[]{new X509TrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }

            @Override
            public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }
        }};
        SSLContext sslContext = null;
        try {
            sslContext = SSLContext.getInstance("TLS");
        } catch (NoSuchAlgorithmException e) {
            System.err.println("--------------------------HTTPS--证书出错！");
            e.printStackTrace();
        }
        try {
            sslContext.init(null, trustManagers, new SecureRandom());
        } catch (KeyManagementException e) {
            System.err.println("--------------------------HTTPS--证书初始化出错！");
            e.printStackTrace();
        }

        this.client = new OkHttpClient.Builder()
                .callTimeout(120, TimeUnit.SECONDS)
                .sslSocketFactory(sslContext.getSocketFactory(), (X509TrustManager) trustManagers[0])
                .build();

    }

    @Override
    public MyResult pages(GptWebaccount dto, MyPageBand pageBand) {

        MyResult result = new MyResult();

        GptWebaccountMapper webaccountMapper = getBaseMapper();

        IPage<GptWebaccount> pages = webaccountMapper.pages(PageDTO.of(pageBand.getPage(), pageBand.getSize()), dto);

        // 根据分页的结果封装返回数据
        MyPager<GptWebaccount> pager = new MyPager<>();
        pager.setTotal(pages.getTotal());
        pager.setPage(pageBand.getPage());
        pager.setPageSize(pageBand.getSize());
        pager.setRows(pages.getRecords());

        result.setData(pager);
        result.setMsg("查询成功！");

        return result;
    }

    @Override
    public MyResult mylist(GptWebaccount dto) {

        MyResult result = new MyResult();

        GptWebaccountMapper webaccountMapper = getBaseMapper();

        List<GptWebaccount> list = webaccountMapper.myList(dto);

        result.setData(list);
        result.setMsg("查询成功！");

        return result;
    }

    @Override
    public MyResult getByID(String id) {

        MyResult result = new MyResult();

        GptWebaccountMapper webaccountMapper = getBaseMapper();

        GptWebaccount gptWebaccount = webaccountMapper.selectById(id);

        if(gptWebaccount!=null){
            result.setMsg("查询成功！");
            result.setData(gptWebaccount);
        }else{
            result.setMsg("查询失败！");
            result.setCode("9999");
        }

        return result;
    }

    @Override
    public MyResult add(GptWebaccount dto) {

        MyResult result = new MyResult();

        dto.setWebAccountID(IdUtil.fastSimpleUUID());

        boolean save = save(dto);

        // 进行记录
        GptWebaccountInfo info = new GptWebaccountInfo();
        info.setWebAccountID(dto.getWebAccountID());
        info.setInfoTime(new Date());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        info.setInfoDesc("【"+dto.getWebAccountTypeName()+"账号】"+dto.getAccountCode()+"，于"+sdf.format(dto.getRegisterTime())+"注册，然后添加进入账号库");
        infoMapper.insert(info);

        if(save){
            result.setMsg("添加成功！");
        }else{
            result.setMsg("添加失败！");
            result.setCode("9999");
        }

        return result;
    }

    @Override
    public MyResult update(GptWebaccount dto) {

        MyResult result = new MyResult();

        // 查询旧的数据
        GptWebaccount oldData = this.getById(dto.getWebAccountID());

        // 要保存的记录信息
        GptWebaccountInfo info = new GptWebaccountInfo();
        info.setWebAccountID(dto.getWebAccountID());
        info.setInfoTime(new Date());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String infoString = "账号在"+sdf.format(new Date())+"进行了数据修改,修改内容如下：/n";
        if(!oldData.getAccountCode().equals(dto.getAccountCode())){
            infoString += "账号名：从：【"+oldData.getAccountCode()+"】，修改为：【"+dto.getAccountCode()+"】/n";
        }
        if(!oldData.getAccountPwd().equals(dto.getAccountPwd())){
            infoString += "密码：从：【"+oldData.getAccountPwd()+"】，修改为：【"+dto.getAccountPwd()+"】/n";
        }
        if(!oldData.getAccountEmail().equals(dto.getAccountEmail())){
            infoString += "注册邮箱：从：【"+oldData.getAccountEmail()+"】，修改为：【"+dto.getAccountEmail()+"】/n";
        }
        if(!oldData.getAccountCountry().equals(dto.getAccountCountry())){
            infoString += "注册国家：从：【"+oldData.getAccountCountry()+"】，修改为：【"+dto.getAccountCountry()+"】/n";
        }
        if(dto.getAccountPhoneNumber()!=null){
            if(oldData.getAccountPhoneNumber()!=null){
                if(!oldData.getAccountPhoneNumber().equals(dto.getAccountPhoneNumber())){
                    infoString += "注册手机：从：【"+oldData.getAccountPhoneNumber()+"】，修改为：【"+dto.getAccountPhoneNumber()+"】/n";
                }
            }else{
                infoString += "注册手机：从：【无】，修改为：【"+dto.getAccountPhoneNumber()+"】/n";
            }
        }

        if(!oldData.getWebAccountName().equals(dto.getWebAccountName())){
            infoString += "账号状态：从：【"+oldData.getWebAccountName()+"】，修改为：【"+dto.getWebAccountName()+"】/n";
        }
        if(!oldData.getWebAccountTypeName().equals(dto.getWebAccountTypeName())){
            infoString += "账号类型：从：【"+oldData.getWebAccountTypeName()+"】，修改为：【"+dto.getWebAccountTypeName()+"】/n";
        }
        if(!oldData.getWebStaffName().equals(dto.getWebStaffName())){
            infoString += "所属客户：从：【"+oldData.getWebStaffName()+"】，修改为：【"+dto.getWebStaffName()+"】/n";
        }
        if(dto.getApiKey()!=null){
            if(oldData.getApiKey()!=null){
                if(!oldData.getApiKey().equals(dto.getApiKey())){
                    infoString += "秘钥信息：从：【"+oldData.getApiKey()+"】，修改为：【"+dto.getApiKey()+"】/n";
                }
            }else{
                infoString += "秘钥信息：从：【无】，修改为：【"+dto.getApiKey()+"】/n";
            }
        }
        if(!oldData.getAccountEmailPwd().equals(dto.getAccountEmailPwd())){
            infoString += "邮箱密码：从：【"+oldData.getAccountEmailPwd()+"】，修改为：【"+dto.getAccountEmailPwd()+"】/n";
        }
        info.setInfoDesc(infoString);
        infoMapper.insert(info);

        boolean b = updateById(dto);

        if(b){
            result.setMsg("修改成功！");
        }else{
            result.setMsg("修改失败！");
            result.setCode("9999");
        }

        return result;
    }

    @Override
    public MyResult deletes(String ids) {

        MyResult result = new MyResult();

        String[] split = ids.split(",");

        List<String> list = Arrays.asList(split);

        boolean b = removeByIds(list);

        for(String tempID : list){
            // 进行记录
            GptWebaccountInfo info = new GptWebaccountInfo();
            info.setWebAccountID(tempID);
            info.setInfoTime(new Date());
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            info.setInfoDesc("当前账号于"+(sdf.format(new Date()))+"被删除");
            infoMapper.insert(info);
        }

        if(b){
            result.setMsg("删除成功！");
        }else{
            result.setMsg("删除失败！");
            result.setCode("9999");
        }

        return result;
    }

    @Override
    public MyResult getAccountInfo(String id) {

        MyResult result = new MyResult();

        QueryWrapper<GptWebaccountInfo> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("webAccountID",id);
        queryWrapper.orderByDesc("infoTime");

        List<GptWebaccountInfo> gptWebaccountInfos = infoMapper.selectList(queryWrapper);

        result.setMsg("查询成功！");
        result.setData(gptWebaccountInfos);

        return result;
    }

    @Override
    public MyResult infoChangePwd(GptWebaccount dto) {

        MyResult result = new MyResult();

        // 查询旧的数据
        GptWebaccount oldData = this.getById(dto.getWebAccountID());

        // 进行记录
        GptWebaccountInfo info = new GptWebaccountInfo();
        info.setWebAccountID(dto.getWebAccountID());
        info.setInfoTime(new Date());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        info.setInfoDesc("密码从：【"+oldData.getAccountPwd()+"】，修改为：【"+dto.getAccountPwd()+"】");
        infoMapper.insert(info);

        boolean b = this.updateById(dto);

        if(b){
            result.setMsg("修改记录成功！");
        }else{
            result.setMsg("修改记录失败！");
            result.setCode("9999");
        }

        return result;
    }

    @Override
    public MyResult lessAccount(GptWebaccount dto) {

        MyResult result = new MyResult();

        // 进行记录
        GptWebaccountInfo info = new GptWebaccountInfo();
        info.setWebAccountID(dto.getWebAccountID());
        info.setInfoTime(new Date());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        info.setInfoDesc("账号租借给：【"+dto.getWebStaffName()+"】，时间：从"+(sdf.format(dto.getLeaseStartTime()))+"至"+sdf.format(dto.getLeaseEndTime()));
        infoMapper.insert(info);

        dto.setWebAccountCode("2");
        dto.setWebAccountName("租借中");

        boolean b = this.updateById(dto);

        if(b){
            result.setMsg("租借记录添加成功！");
        }else{
            result.setMsg("租借记录添加失败！");
            result.setCode("9999");
        }

        return result;
    }

    @Override
    public MyResult updateGptLimit(GptWebaccount dto) {

        MyResult result = new MyResult();
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        Map<String, Object> resMap = this.HttpGPTSubscription(dto.getApiKey());

        Date useEndDate = new Date();

        Calendar c = Calendar.getInstance();
        c.add(Calendar.DAY_OF_MONTH, -90);
        Date useStartDate = c.getTime();
        Map<String, Object> resMap2 = this.HttpGPTUsage(dto.getApiKey(), sdf.format(useStartDate), sdf.format(useEndDate));

        // 过期时间
        dto.setGptPassTime(sdf.format(new Date(((Integer) resMap.get("access_until")))));
        // 额度
        dto.setGptLimit(String.valueOf((BigDecimal) resMap.get("hard_limit_usd")));
        // 已使用额度
        BigDecimal bigTotalUsage = (BigDecimal) resMap2.get("total_usage");
        double totalUsage = (bigTotalUsage.doubleValue()) / 100;

        dto.setGptLimitUsed(String.valueOf(totalUsage));
        // 剩余额度
        BigDecimal hlu = (BigDecimal) resMap.get("hard_limit_usd");
        BigDecimal tu = new BigDecimal(String.valueOf(totalUsage));
        BigDecimal subtract = hlu.subtract(tu);
        dto.setGptLimitLess(subtract.toString());

        // 进行记录
        GptWebaccountInfo info = new GptWebaccountInfo();
        info.setWebAccountID(dto.getWebAccountID());
        info.setInfoTime(new Date());

        info.setInfoDesc("账号更新信息：总额度："+dto.getGptLimit()+"，已使用："+dto.getGptLimitUsed()+"，剩余："+dto.getGptLimitLess()+"，有效期结束："+dto.getGptPassTime()+"，记录时间："+(sdf.format(new Date())));
        infoMapper.insert(info);

        boolean b = updateById(dto);

        if(b){
            result.setMsg("GPT余额信息更新成功！");
        }else{
            result.setMsg("GPT余额信息更新失败！");
            result.setCode("9999");
        }

        return result;
    }

    @Override
    public MyResult saleAccount(GptWebaccount dto) {
        MyResult result = new MyResult();

        // 进行记录
        GptWebaccountInfo info = new GptWebaccountInfo();
        info.setWebAccountID(dto.getWebAccountID());
        info.setInfoTime(new Date());
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        info.setInfoDesc("账号售出给："+dto.getWebStaffName()+"，时间："+sdf.format(new Date()));
        infoMapper.insert(info);

        dto.setWebAccountCode("3");
        dto.setWebAccountName("已售出");
        boolean b = updateById(dto);

        if(b){
            result.setMsg("售出记录更新成功！");
        }else{
            result.setMsg("售出记录更新失败！");
            result.setCode("9999");
        }

        return result;
    }

    @Override
    public MyResult updateAllGptLimit() {

        MyResult result = new MyResult();

        // 查询出所有的账号信息
        QueryWrapper<GptWebaccount> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("isDelete",0);
        queryWrapper.isNotNull("apiKey");

        List<GptWebaccount> list = this.list(queryWrapper);

        for(GptWebaccount dto : list){
            this.updateGptLimit(dto);
        }

        return result;
    }

    @Override
    public List<String> getCanUseGptApiKeys() {

        QueryWrapper<GptWebaccount> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("isDelete",0);
        queryWrapper.isNotNull("apiKey");
        queryWrapper.gt("gptLimitLess","0");
        queryWrapper.orderByDesc("gptLimitLess");

        List<GptWebaccount> list = this.list(queryWrapper);

        List<String> apikeys = new ArrayList<>();

        for(GptWebaccount a : list){
            apikeys.add(a.getApiKey());
        }


        return apikeys;
    }


    /**
     * 查询当前idkey使用记录
     * @param apiKey
     * @param startDate
     * @param endDate
     */
    public Map<String,Object> HttpGPTUsage(String apiKey,String startDate,String endDate){

        System.err.println("------------------PATH:"+gptpath);
        Request request = new Request.Builder()
                .url(gptpath+"v1/dashboard/billing/usage?start_date="+startDate+"&end_date="+endDate)
                .addHeader("Authorization","Bearer "+apiKey)
                .addHeader("content-type","application/json")
                .build();


        try {
            Response response = client.newCall(request).execute();

            return (Map)JSON.parse(response.body().string());
        } catch (IOException e) {
            e.printStackTrace();
            System.err.println("GPT-查询当前idkey使用情况-异常！");
        }

        return null;
    }

    /**
     * 查询当前idkey使用情况
     * @param apiKey
     */
    public Map<String,Object> HttpGPTSubscription(String apiKey){
        System.err.println("------------------PATH:"+gptpath);
        Request request = new Request.Builder()
                .url(gptpath+"dashboard/billing/subscription")
                .addHeader("Authorization","Bearer "+apiKey)
                .addHeader("content-type","application/json")
                .build();


        try {
            Response response = client.newCall(request).execute();

            return (Map)JSON.parse(response.body().string());
        } catch (IOException e) {
            e.printStackTrace();
            System.err.println("GPT-查询当前idkey使用情况-异常！");
        }

        return null;
    }

}
